home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / PKTDRVR.C < prev    next >
Text File  |  1990-07-12  |  9KB  |  397 lines

  1. /* Driver for FTP Software's packet driver interface */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #include "enet.h"
  6. #include "iface.h"
  7. #include "ec.h"
  8. #include "timer.h"
  9. #include "arp.h"
  10. #include "trace.h"
  11. #include "regs.h"
  12. #include "pktdrvr.h"
  13.  
  14. struct pktdrvr pktdrvr[PK_MAX];
  15. unsigned int npk;
  16. int derr;
  17.  
  18. extern int need_disable;
  19.  
  20. /* Send raw packet (caller provides header) */
  21. int
  22. pk_raw(interface,bp)
  23. struct interface *interface;    /* Pointer to interface control block */
  24. struct mbuf *bp;        /* Data field */
  25. {
  26.     register struct pktdrvr *pp;
  27.     int16 size;
  28.     struct mbuf *bp1;
  29.  
  30.     pp = &pktdrvr[interface->dev];
  31.     size = len_mbuf(bp);
  32.  
  33.     switch(pp->class){
  34.     case ETHERNET:
  35.         dump(interface,IF_TRACE_OUT,TRACE_ETHER,bp);
  36.         if(size < 60)
  37.             size = 60;
  38.         break;
  39.     case SERIAL_LINE:
  40.         dump(interface,IF_TRACE_OUT,TRACE_IP,bp);
  41.         break;
  42.     }
  43.     if(bp->next != NULLBUF){
  44.         /* Copy to contiguous buffer, since driver can't handle mbufs */
  45.         bp1 = copy_p(bp,size);
  46.         free_p(bp);
  47.         bp = bp1;
  48.         if(bp == NULLBUF)
  49.             return -1;
  50.     } else
  51.         bp->cnt = size;    /* Make sure packet size is big enough */
  52.  
  53.     send_pkt(pp->intno,bp->data,bp->cnt);
  54.     free_p(bp);
  55.     return 0;
  56. }
  57.  
  58. /* Packet driver receive routine. Called from an assembler hook that pushes
  59.  * the caller's registers on the stack so we can access and modify them.
  60.  * This is a rare example of call-by-location in C.
  61.  */
  62. int
  63. pkint(di,si,bp,dx,cx,bx,ax,ds,es)
  64. unsigned short di,si,bp,dx,cx,bx,ax,ds,es;
  65. {
  66.     register struct pktdrvr *pp;
  67.     int i;
  68.  
  69.     for(i=0,pp = &pktdrvr[0];i < npk;i++,pp++)
  70.         if(pp->handle1 == bx
  71.          || (pp->class == ETHERNET && pp->handle2 == bx))
  72.             break;
  73.     if(i == npk)
  74.         return;    /* Unknown packet */
  75.  
  76.     switch(ax){
  77.     case 0:    /* Space allocate call */
  78.         if(pp->rcvcnt < pp->rcvmax && (pp->buffer = alloc_mbuf(cx)) != NULLBUF){
  79.             es = FP_SEG(pp->buffer->data);
  80.             di = FP_OFF(pp->buffer->data);
  81.             pp->buffer->cnt = cx;
  82.         } else {
  83.             es = di = 0;
  84.         }
  85.         break;
  86.     case 1:    /* Packet complete call */
  87.         enqueue(&pp->rcvq,pp->buffer);
  88.         pp->rcvcnt++;
  89.         pp->buffer = NULLBUF;
  90.         break;
  91.     default:
  92.         break;
  93.     }
  94. }
  95. /* Process any incoming packets on the receive queue */
  96. int
  97. pk_recv(interface)
  98. struct interface *interface;
  99. {
  100.     void arp_input();
  101.     int ip_route();
  102.     struct pktdrvr *pp;
  103.     struct mbuf *bp;
  104.  
  105.     pp = &pktdrvr[interface->dev];
  106.     if((bp = dequeue(&pp->rcvq)) == NULLBUF)
  107.         return 0;
  108.  
  109.     pp->rcvcnt--;
  110.     switch(pp->class){
  111.     case ETHERNET:
  112.         dump(interface,IF_TRACE_IN,TRACE_ETHER,bp);
  113.         eproc(interface,bp);
  114.         break;
  115.     case SERIAL_LINE:
  116.         dump(interface,IF_TRACE_IN,TRACE_IP,bp);
  117.         ip_route(bp,0);
  118.         break;
  119.     }
  120.  
  121.     return 1;
  122. }
  123. /* Shut down the packet interface */
  124. pk_stop(interface)
  125. struct interface *interface;
  126. {
  127.     struct pktdrvr *pp;
  128.  
  129.     pp = &pktdrvr[interface->dev];
  130.     /* Call driver's release_type() entry */
  131.     if(release_type(pp->intno,pp->handle1) == -1)
  132.         printf("%s: release_type error code %u\n",interface->name,derr);
  133.  
  134.     if(pp->class == ETHERNET)
  135.         release_type(pp->intno,pp->handle2);
  136. }
  137. /* Attach a packet driver to the system
  138.  * argv[0]: hardware type, must be "packet"
  139.  * argv[1]: software interrupt vector, e.g., x7e
  140.  * argv[2]: interface label, e.g., "trw0"
  141.  * argv[3]: maximum number of packets allowed on receive queue, e.g., "5"
  142.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  143.  */
  144. pk_attach(argc,argv)
  145. int argc;
  146. char *argv[];
  147. {
  148.     register struct interface *if_pk;
  149.     register struct pktdrvr *pp;
  150.     extern struct interface *ifaces;
  151.     int class,i;
  152.     unsigned int intno;
  153.     char far *drvvec;
  154.     static char iptype[] = {IP_TYPE >> 8,IP_TYPE};
  155.     static char arptype[] = {ARP_TYPE >> 8,ARP_TYPE};
  156.     static char sig[] = PKT_SIG;
  157.     int pether(),gaether(),enet_send(),enet_output(),slip_send();
  158.     void pkvec();
  159. #ifndef __TURBOC__
  160.     void (*getvect())();
  161. #endif
  162.  
  163.     if(npk >= PK_MAX){
  164.         printf("Too many packet drivers\n");
  165.         return -1;
  166.     }
  167.  
  168.     intno = htoi(argv[1]);
  169.     /* Verify that there's really a packet driver there, so we don't
  170.      * go off into the ozone (if there's any left)
  171.      */
  172.     drvvec = getvect(intno);
  173.     for(i = 0; i < strlen(sig); i++){
  174.         if(drvvec[i + 3] != sig[i]){
  175.             printf("No packet driver loaded at int 0x%x\n",intno);
  176.             return -1;
  177.         }
  178.     }
  179.     if((if_pk = (struct interface *)calloc(1,sizeof(struct interface))) == NULLIF
  180.      ||(if_pk->name = malloc((unsigned)strlen(argv[2])+1)) == NULLCHAR){
  181.         if(if_pk != NULLIF)
  182.             free((char *)if_pk);
  183.         printf("pk_attach: no memory!\n");
  184.         return -1;
  185.     }
  186.     pp = &pktdrvr[npk];
  187.     strcpy(if_pk->name,argv[2]);
  188.     pp->rcvmax = atoi(argv[3]);
  189.     if_pk->mtu = atoi(argv[4]);
  190.     if_pk->dev = npk++;
  191.     if_pk->raw = pk_raw;
  192.     if_pk->recv = pk_recv;
  193.     if_pk->stop = pk_stop;
  194.     pp->intno = intno;
  195.  
  196.     /* Find out by exhaustive search what class this driver is (ugh) */
  197.     for(class=0;class<9;class++){
  198.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  199.         if(pp->handle1 != -1)
  200.             break;
  201.     }
  202.     /* Now that we know, release it and do it all over again with the
  203.      * right type fields
  204.      */
  205.     release_type(intno,pp->handle1);
  206.     switch(class){
  207.     case ETHERNET:
  208.         pp->handle1 = access_type(intno,class,ANYTYPE,0,iptype,2,pkvec);
  209.         pp->handle2 = access_type(intno,class,ANYTYPE,0,arptype,2,pkvec);            
  210.         if_pk->send = enet_send;
  211.         if_pk->output = enet_output;
  212.         /* Get hardware Ethernet address from driver */
  213.         if_pk->hwaddr = malloc(EADDR_LEN);
  214.         get_address(intno,pp->handle1,if_pk->hwaddr,EADDR_LEN);
  215.         arp_init(ARP_ETHER,EADDR_LEN,IP_TYPE,ARP_TYPE,ether_bdcst,pether,gaether);
  216.         break;
  217.     case SERIAL_LINE:
  218.         pp->handle1 = access_type(intno,class,ANYTYPE,0,NULLCHAR,0,pkvec);
  219.         if_pk->send = slip_send;
  220.         break;
  221.     default:
  222.         printf("Packet driver has unsupported class %u\n",class);
  223.         free(if_pk->name);
  224.         free((char *)if_pk);
  225.         npk--;
  226.         return -1;
  227.     }
  228.     pp->class = class;
  229.     if_pk->next = ifaces;
  230.     ifaces = if_pk;
  231.     need_disable = 1;        /* must disable ints in malloc! */
  232.  
  233.     return 0;
  234. }
  235. static int
  236. access_type(intno,if_class,if_type,if_number,type,typelen,receiver)
  237. int intno;
  238. int if_class;
  239. int if_type;
  240. int if_number;
  241. char *type;
  242. unsigned typelen;
  243. void (*receiver)();
  244. {
  245. #ifndef __TURBOC__
  246.     struct regs regs;
  247. #endif
  248.  
  249.     _AH = ACCESS_TYPE;    /* Access_type() function */
  250.     _AL = if_class;        /* Class */
  251.     _BX = if_type;            /* Type */
  252.     _DL = if_number;        /* Number */
  253.     /* Packet type template */
  254.     _DS = FP_SEG(type);
  255.     _SI = FP_OFF(type);
  256.     _CX = typelen;            /* Length of type */
  257.     /* Address of receive handler */
  258.     _ES = FP_SEG(receiver);
  259.     _DI = FP_OFF(receiver);
  260. #ifdef __TURBOC__
  261.         geninterrupt(intno);
  262.     asm jc error;
  263.     return _AX;
  264. error:
  265.     derr = _DH;
  266.     return -1;
  267. #else
  268.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  269.         derr = _DH;
  270.         return -1;
  271.     } else
  272.         return _AX;
  273. #endif
  274. }
  275. static int
  276. release_type(intno,handle)
  277. int intno;
  278. int handle;
  279. {
  280. #ifndef __TURBOC__
  281.     struct regs regs;
  282. #endif
  283.  
  284.     _AH = RELEASE_TYPE;
  285.     _BX = handle;
  286. #ifdef __TURBOC__
  287.         geninterrupt(intno);
  288.     asm jc error;
  289.     return 0;
  290. error:
  291.     derr = _DH;
  292.     return -1;
  293. #else
  294.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  295.         derr = _DH;
  296.         return -1;
  297.     } else
  298.         return 0;
  299. #endif
  300. }
  301. static int
  302. send_pkt(intno,buffer,length)
  303. int intno;
  304. char *buffer;
  305. unsigned length;
  306. {
  307. #ifndef __TURBOC__
  308.     struct regs regs;
  309. #endif
  310.  
  311.     _AH = SEND_PKT;
  312.     _DS = FP_SEG(buffer);
  313.     _SI = FP_OFF(buffer);
  314.     _CX = length;
  315. #ifdef __TURBOC__
  316.         geninterrupt(intno);
  317.     asm jc error;
  318.     return 0;
  319. error:
  320.     derr = _DH;
  321.     return -1;
  322. #else
  323.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  324.         derr = _DH;
  325.         return -1;
  326.     } else
  327.         return 0;
  328. #endif
  329. }
  330. static int
  331. driver_info(intno,handle,version,class,type,number,basic)
  332. int intno;
  333. int handle;
  334. int *version,*class,*type,*number,*basic;
  335. {
  336. #ifndef __TURBOC__
  337.     struct regs regs;
  338. #endif
  339.  
  340.     _AH = DRIVER_INFO;
  341.     _AL = 0xff;
  342.     _BX = handle;
  343. #ifdef __TURBOC__
  344.         geninterrupt(intno);
  345.     asm jnc noerror;
  346.     derr = _DH;
  347.     return -1;
  348. noerror:
  349. #else
  350.     if(sysint(intno,®s,®s) & FLAG_CARRY){
  351.         derr = _DH;
  352.         return -1;
  353.     }
  354. #endif
  355.     if(version != NULL)
  356.         *version = _BX;
  357.     if(class != NULL)
  358.         *class = _CH;
  359.     if(type != NULL)
  360.         *type = _DX;
  361.     if(number